package com.kylin.common.taglib;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Locale;

import javax.servlet.jsp.JspException;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.log4j.Logger;
import org.apache.struts.Globals;
import org.apache.struts.taglib.html.BaseHandlerTag;

import com.kylin.common.dict.ISelectOption;
import com.kylin.common.exception.SystemException;
import com.kylin.common.util.MemObjFactory;

/**
 * 生成下拉菜单
 * 
 * @author lzh
 *
 */
public class SelectTag extends BaseHandlerTag{
	protected static Logger log = Logger.getLogger(SelectTag.class);
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/** 下拉菜单缺省值 */
	protected String value;

	/** 不使用property时定义的下拉菜单名 */
	protected String name;
	
	/** 接受actionform 的属性 */
	protected String property;

	/** 页面传入的list数据 */
	protected String listName;

	/** 内存中字典数据名 */
	protected String dictName;

	/** 数据的所属语言种类,如果传入all 或 ALL 则返回所有语言种类的数据 */
	protected String language;

	protected String multiple;

	protected String size;
	
	protected String[] match;

	/** 是否禁止首项为空 */
	protected String notEmpty;

	/** struts的ActionForm 在配置文件中的formName*/
	protected String formName;

	/** 本页面ActionForm 的真实 classname  */
	protected String formClass;

	public int doStartTag() throws JspException {

		// pageContext.setAttribute("taglib.html.AllLanguageSelectTag", this);
		try {
			setValueByFormValue();
			try {
				getMatchValue();
			} catch (Exception e) {
				throw new JspException(e);
			}
			pageContext.getOut().println(getStartElement());
			try {
				pageContext.getOut().println(getOptions());
			} catch (Exception e) {
				log.error("构造下拉菜单异常："+e,e);
//				throw new Exception ("加载内存对象("+listName+")时发生异常:"+e, e);
			}
			pageContext.getOut().println("</select>");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return SKIP_BODY;
	}

	private String getStartElement() throws JspException {
		StringBuffer sb = new StringBuffer("<select");
		sb.append(" name=\"");
		sb.append(this.name);
		sb.append("\"");
		if (multiple != null)
			sb.append(" multiple=\"multiple\"");
		if (size != null) {
			sb.append(" size=\"");
			sb.append(size);
			sb.append("\"");
		}
		sb.append(prepareEventHandlers());
		sb.append(prepareStyles());
		sb.append(">");
		return sb.toString();
	}

	protected String getOptions() throws InstantiationException,
			IllegalAccessException, ClassNotFoundException {
		if (language == null || language.equals("")){
			Locale local = (Locale) pageContext.getAttribute(Globals.LOCALE_KEY, pageContext.SESSION_SCOPE);
			if(local != null)
		    	language = local.toString();
		}
		StringBuffer sb = new StringBuffer();
		if (this.notEmpty == null || !notEmpty.equalsIgnoreCase("true"))
			sb.append("<option value=''> </option>");
		List datas = null;
		if(listName !=  null)
			datas = (List)pageContext.getAttribute(listName);
		else if(dictName != null){
			try{
				if("all".equalsIgnoreCase(language))
					datas = MemObjFactory.getDict(dictName);
				else
					datas = MemObjFactory.getDict(dictName, language);
			}catch(SystemException e){
				datas = null;
			}
		}else{
			throw new SystemException("未指定下拉菜单的数据源，请定义listName 或 dictName");
		}
		
		if(formName != null && formName.equals("")){
		}
		if(datas == null || datas.size() == 0)
			return "<option>-- 无选项 --</option>";
		for (int i = 0; i < datas.size(); i++) {
			ISelectOption bean = (ISelectOption)datas.get(i);
	
			sb.append("\n<option value=\"").append(bean.getValue()).append("\"");
			sb.append(getFieldStr(bean));
			if(matchValue(bean.getValue()))
				sb.append(" selected='true' ");
			sb.append(">");
			sb.append(bean.getName()).append("</option>");
		}
		return sb.toString();
	}

	protected void setValueByFormValue(){
		if(formName == null || formName.equals(""))
			return ;
		Object formBean = pageContext.getAttribute(formName,pageContext.REQUEST_SCOPE);
		if(formBean == null)
			throw new SystemException("未找到ActionForm ：" + formName);
		Method[] ms = formBean.getClass().getDeclaredMethods();
	    String methodName = "get";
	    if(name ==null || name.equals(""))
	    	throw new SystemException("mytag:select 标签缺少 name 属性");
	    methodName += name.substring(0,1).toUpperCase();
	    methodName += name.substring(1,name.length());
	    for(int i=0;i<ms.length;i++){
	    if(ms[i].getName().equals(methodName) )
			try {
				System.out.print("methodName="+methodName);
				Object v = ms[i].invoke(formBean,null);
				if(v != null)
					value = v.toString();
			} catch (Exception e) {
				e.printStackTrace();
			} 
	    }
		
	}
	private String getFieldStr(Object obj){
		StringBuffer sb = new StringBuffer(" ");
		Field[] fs =obj.getClass().getDeclaredFields();
    	for(int i=0;i<fs.length;i++){
    		try {
    			Object value = fs[i].get(obj);
    			if(value != null)
    				sb.append(fs[i].getName()).append("=\"")
    				     .append(value).append("\" ");
			} catch (Exception e) {
				
			}
    	}	
    	return sb.toString();
	}
	
	protected void getMatchValue() throws IllegalAccessException,
			InvocationTargetException {
		if(this.value == null)
			return ;
		String[] beans = this.value.split("\\.");
		if (beans.length < 2){
			this.match = new String[1];
			this.match[0] = this.value;
			return;
		}
		Object obj = pageContext.findAttribute(beans[0]);
		try {
			for (int i = 1; i < beans.length - 1; i++) {
				if (obj == null)
					throw new NoSuchMethodException("Unknown property "
							+ beans[i - 1]);
				obj = PropertyUtils.getProperty(obj, beans[i]);
			}
			this.match = BeanUtils.getArrayProperty(obj,
					beans[beans.length - 1]);

		} catch (NoSuchMethodException e) {
			this.match = new String[1];
			this.match[0] = this.value;
		}
	}

	public static void main(String[] s) {
		String str = "menber.option.text";
		String[] namestrs = str.split("\\@");
		for (int i = 0; i < namestrs.length; i++) {
			System.out.print("\ni=" + namestrs[i]);
		}
	}

	protected boolean matchValue(String v) {
		if (this.match == null || this.match.length == 0)
			return false;
		for (int i = 0; i < this.match.length; i++) {
//System.out.println("match(v="+v+",mv="+match[i]+")")	;		
			if (match[i] != null)
				if (match[i].equals(v))
					return true;
		}
		return false;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	

	public void setMultiple(String multiple) {
		this.multiple = multiple;
	}

	public String getListName() {
		return listName;
	}

	public void setListName(String listName) {
		this.listName = listName;
	}

	public String getNotEmpty() {
		return notEmpty;
	}

	public void setNotEmpty(String notEmpty) {
		this.notEmpty = notEmpty;
	}

	public String getProperty() {
		return property;
	}

	public void setProperty(String property) {
		this.property = property;
	}

	public String getDictName() {
		return dictName;
	}

	public void setDictName(String dictName) {
		this.dictName = dictName;
	}

	public String getLanguage() {
		return language;
	}

	public void setLanguage(String language) {
		this.language = language;
	}

	public String getFormClass() {
		return formClass;
	}

	public void setFormClass(String formClass) {
		this.formClass = formClass;
	}

	public String getFormName() {
		return formName;
	}

	public void setFormName(String formName) {
		this.formName = formName;
	}

	public String getSize() {
		return size;
	}

	public void setSize(String size) {
		this.size = size;
	}

	public String getMultiple() {
		return multiple;
	}

	public int doEndTag() throws JspException {
		this.language = null;
		return super.doEndTag();
	}

}
